﻿using System;
using System.Linq;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Eneta.Portal.Common;
using Eneta.Portal.Common.Helpers;
using Eneta.Portal.Common.Repository;
using Eneta.Portal.Common.Services;
using FredCK.FCKeditorV2;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Utilities;

namespace Eneta.Portal.Literature.Pages
{
    public class BookEditPage : LiteratureEditPage
    {
        protected Literal titleLabel;
        protected TextBox nameField;
        protected FCKeditor descriptionField;
        protected FileUpload pictureUpload;
        protected TextBox authorsField;
        protected TextBox publishingYearField;
        protected TextBox pageCountField;
        protected TextBox ISBN10Field;
        protected TextBox ISBN13Field;
        protected TextBox additionalInfoField;
        protected HtmlGenericControl previewImage;
        protected HtmlImage bookPreviewImage;
        
        protected Button saveButton;
        protected HtmlAnchor cancelLink;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            saveButton.Click += saveButton_Click;
            previewImage.Visible = false;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (SPContext.Current.Web.CurrentUser == null)
            {
                Logger.LogInfo("Kasutaja on anonüümne, suuname ümber", "BookEditPage_OnLoad");
                Response.Redirect("/oppimine/raamatud", false);
                return;
            }

            ClearStyles();

            if (IsPostBack)
                return;

            titleLabel.Text = "Raamatu lisamine";
            additionalInfoField.Text = "http://";
            BindItem();
        }       

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            ApplyErrors(Errors);

            if (string.IsNullOrEmpty(additionalInfoField.Text) || additionalInfoField.Text == "http://")
            {
                additionalInfoField.CssClass = "text-go";
                additionalInfoField.Text = "http://";
            }
            else
                additionalInfoField.CssClass = "text-go";
        }


        #region Events

        void saveButton_Click(object sender, EventArgs e)
        {
            string operation = string.Empty;

            if (additionalInfoField.Text == "http://")
            {
                additionalInfoField.Text = string.Empty;
            }
            
            //Valideerimime sisendi
            if (!IsValidInput())
            {
                //Todo: Apply errrors
                Logger.LogInfo("Cannot save book, validation errors", GetType().ToString());
                return;
            }

            AddApproverRoleToUser();

            Logger.LogInfo("Raamatu kinnitamise juurde:", GetType().ToString());
            try
            {
                var site = SPContext.Current.Site;
                var web = SPContext.Current.Web;
                var siteId = site.ID;

                if (Item == null)
                {
                    Logger.LogInfo("saveButton_Click", "BookEdit.cs");
                    SavePage();
                }
                else
                {
                    Logger.LogInfo("saveButton_Click", "BookEdit.cs");
                    if (SPContext.Current.Web.CurrentUser.IsSiteAdmin || IsAuthor)
                    {
                        UpdatePage(web);
                    }
                    else
                    {
                        Logger.LogInfo("Kasutaja ei ole administraator, suuname ümber", "BookEditPage_SaveButton_Click");
                        Response.Redirect("/oppimine/raamatud", false);
                        return;
                    }
                    
                }

                if (pictureUpload.HasFile)
                {
                    SavePicture(UrlHelper.GetPageFileName(nameField.Text), siteId, pictureUpload.FileContent, "Raamat");
                }

            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                RemoveApproverRoleFromUser();
            }


            RemoveApproverRoleFromUser();

            if (Item == null)
            {

                SendMessage();
                
            }
            PublishingWeb currentWeb = PublishingWeb.GetPublishingWeb(SPContext.Current.Web);
            SPList list = currentWeb.Web.Lists[PublishingWeb.GetPagesListId(currentWeb.Web)];
            string url = "/oppimine/raamatud";
            if (Item != null)
            {
                if (Item.Title != nameField.Text)
                {
                    url = string.Format("{0}/{1}?msg=bookedit", list.RootFolder.ServerRelativeUrl, UrlHelper.GetPageFileName(nameField.Text));
                }
                else
                {
                    url = Item.ItemUrl + "?msg=bookedit";
                }
            }
            else
            {
                url = list.RootFolder.ServerRelativeUrl + "/" + UrlHelper.GetPageFileName(nameField.Text) + "?msg=booksave";
            }
            Response.Redirect(url, false);
        }

        private void UpdatePage(SPWeb web)
        {
            var tempItem = web.GetListItem(Item.ItemUrl);
            if (tempItem == null)
            {
                Logger.LogInfo("Book  listitem not found", "BookEditPage_UpdatePage");
                return;
            }
            var oldName = tempItem.Title;
            var id = tempItem.ID;

            var publishingPage = PublishingPage.GetPublishingPage(tempItem);
            if (oldName != nameField.Text)
            {
                var newItem = RenamePage(publishingPage, nameField.Text);
                if (newItem.Exists)
                {
                    var newPage = PublishingPage.GetPublishingPage(newItem.Item);
                    SetFormValues(newPage, false);
                }
            }
            else
            {
                SetFormValues(publishingPage, false);
            }
        }

        private SPFile RenamePage(PublishingPage publishingPage, string newPageName)
        {
            try
            {
                var web = publishingPage.PublishingWeb.Web;
                var pageName = UrlHelper.GetPageFileName(newPageName);
                string url = publishingPage.ListItem.ParentList.RootFolder.ServerRelativeUrl + "/" + pageName;
                RenamePicture(web, "raamatud", publishingPage.ListItem.File.Name, pageName);
                publishingPage.ListItem.File.MoveTo(url);
                return web.GetFile(url);
            }
            catch (SPException ex)
            {
                Logger.LogException(ex);
            }
            return null;
        }

        private void SavePage()
        {
            var site = SPContext.Current.Site;
            var web = SPContext.Current.Web;

            var list = web.Lists[PublishingWeb.GetPagesListName(web)];
            var pageName = UrlHelper.GetPageFileName(nameField.Text);
            var file = web.GetFile(list.RootFolder.ServerRelativeUrl + "/" + pageName);
            if (!file.Exists)
            {
                Logger.LogInfo("Raamatu  layout page", GetType().ToString());

                PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
                PageLayout bookLayout = GetBookLayout(web);

                if (bookLayout == null)
                {
                    Logger.LogInfo("Raamatu page layout on puudu", "BookEditPage_SavePage");
                    throw new ArgumentNullException("Book page layout is missing");
                }

                var publishingPages = publishingWeb.GetPublishingPages();

                PublishingPage page = publishingPages.Add(list.RootFolder.ServerRelativeUrl + "/" + pageName, bookLayout);

                Logger.LogInfo("SaveButtonClick: Book Publishing page created", GetType().ToString());

                SetFormValues(page, true);

            }
            else
            {
                Logger.LogInfo("Raamat " + file.Name + " already exists", "BookEditPage_SavePage");
                throw new ArgumentException("Book already exsists");
            }
        }

        private void SetFormValues(PublishingPage page, bool newPage)
        {
            var oldName = page.ListItem.Title;
            var oldStatus = page.ListItem.ModerationInformation.Status;
            if (page.ListItem.File.CheckedOutBy != null)
            {
                if (page.ListItem.File.CheckedOutBy.LoginName != SPContext.Current.Web.CurrentUser.LoginName)
                {
                    page.ListItem.File.UndoCheckOut();
                    page.CheckOut();
                }
            }
            else if (page.ListItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.None)
            {
                page.ListItem.File.CheckOut();
            }
            var currentUser = SPContext.Current.Web.CurrentUser;
            page.ListItem[SPBuiltInFieldId.ContentTypeId] = page.Layout.AssociatedContentType.Id;
            if (newPage || oldName != nameField.Text)
                page.ListItem[SPBuiltInFieldId.Title] = nameField.Text;
            page.ListItem["PublishingPageContent"] = descriptionField.Value;
            if (!additionalInfoField.Text.Contains("http://"))
                page.ListItem[Constants.Fields.AdditionalInfoURL.Name] = string.Format("http://{0}", additionalInfoField.Text);
            else 
                page.ListItem[Constants.Fields.AdditionalInfoURL.Name] = additionalInfoField.Text;
            if (!string.IsNullOrEmpty(authorsField.Text))
            page.ListItem[Constants.Fields.Authors.Name] = authorsField.Text;
            if (!string.IsNullOrEmpty(pageCountField.Text))
                page.ListItem[Constants.Fields.PageCount.Name] = pageCountField.Text;
            if (!string.IsNullOrEmpty(publishingYearField.Text))
                page.ListItem[Constants.Fields.PublishYear.Name] = publishingYearField.Text;
            if (!string.IsNullOrEmpty(ISBN10Field.Text))
                page.ListItem[Constants.Fields.ISBN10.Name] = ISBN10Field.Text;
            if (!string.IsNullOrEmpty(ISBN13Field.Text))
                page.ListItem[Constants.Fields.ISBN13.Name] = ISBN13Field.Text;

            if (newPage)
            {
                page.ListItem[SPBuiltInFieldId.Author] = currentUser;
                page.ListItem[Constants.Fields.RealAuthor.Name] = currentUser;
            }

            page.ListItem[SPBuiltInFieldId.Editor] = currentUser;
            
            Logger.LogInfo("SaveButtonClick: Omistatud", GetType().ToString());

            //Record the changes/data

            page.ListItem.Update();
            page.ListItem.File.Update();
            page.Update();

            //Checkin file

            Logger.LogInfo("SaveButtonClick: before publishingPage.CheckIn(string.Empty);", GetType().ToString());
            page.ListItem.File.CheckIn("", SPCheckinType.MajorCheckIn);

            if (!IsAuthor)
            {
                if (!newPage && oldStatus == SPModerationStatusType.Approved)
                {
                    page.ListItem.File.Approve(string.Empty);
                }
                else if (!newPage && Item.Status == SPModerationStatusType.Denied)
                {
                    page.ListItem.File.Deny(string.Empty);
                }
            }
            else
            {
                page.ListItem.File.Publish(string.Empty);
            }
        }

        private PageLayout GetBookLayout(SPWeb web)
        {
            SPContentType ct = null;
            PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
            foreach (SPContentType ct2 in web.AvailableContentTypes)
            {
                if (ct2.Name == "Raamat")
                {
                        ct = ct2;
                        break;
                }
            }
            if (ct == null)
            {
                foreach (var layout in publishingWeb.GetAvailablePageLayouts())
                {
                    if (layout.Name.ToLower() == "eneta.learning.bookdetail.layout.aspx")
                    {
                        return layout;
                    }
                }
            }
            else
            {
                var publishingLayout = publishingWeb.GetAvailablePageLayouts(ct.Id);
                if (publishingLayout.Length != 0)
                {
                    return publishingLayout[0];
                }

            }
            return null;
        }

        private void SendMessage()
        {
            var currentEditor = SPContext.Current.Web.CurrentUser;
            var userMail = currentEditor.Email;
            //var body = "<html><body style=\"font-family:arial;font-size:10pt\">";
            //body += "<p>Hei " + currentEditor.Name + "!</p>";
            //body += "<p>Tänud raamatu \"" + nameField.Text + "\" lisamise eest Eneta portaali. ";
            //body += "Raamat ilmub peale administraatori poolset kinnitamist.</p>";

            //body += "<p>Tervitustega,<br/>";
            //body += "Eneta tiim</p>";
            //body +=
            //    "<a href=\"http://www.eneta.ee\"><img src=\"http://www.eneta.ee/SiteCollectionImages/logod/eneta_logo_250x78_sinine.png\" border=\"0\"></a>";
            //body += "</body></html>";

            //SPUtility.SendEmail(SPContext.Current.Web, false, false, userMail, nameField.Text + " raamat lisati Eneta portaali", body);
            //SPUtility.SendEmail(SPContext.Current.Web, false, false, "abi@eneta.ee", nameField.Text + " raamat lisati Eneta portaali", body);

            var mailer = new MailerService();
            var addresses = new[] { currentEditor.Email, "abi@eneta.ee" };
            mailer.SendMailByTemplate("BookAdded", currentEditor.Name, nameField.Text, null, addresses);
        }

        #endregion


        #region Helpers

        /// <summary>
        /// Check that the input data is valid
        /// </summary>
        /// <returns></returns>
        private bool IsValidInput()
        {
            if (string.IsNullOrEmpty(nameField.Text))
            {
                Errors.Add("name", Resources.Literature.BookTitleIsMissing);
            }
            else if (nameField.Text.Length < 4)
            {
                Errors.Add("name", Resources.Literature.BookTitleTooShort);
            }
            else if (Item == null && new BookRepository(SPContext.Current.Web).BookExists(nameField.Text))
            {
                Errors.Add("name", Resources.Literature.BookAlreadyExists);
            }
            if (string.IsNullOrEmpty(descriptionField.Value))
            {
                Errors.Add("description", Resources.Literature.BookDescriptionIsMissing);
            }

            if (pictureUpload.HasFile)
            {
                if (!ImageHelper.IsValidImage(pictureUpload.FileContent))
                {
                    Errors.Add("picture", Resources.Literature.BookLogoIsIncorrect);
                    
                }
            }

            int publishingYear;
            if (!string.IsNullOrEmpty(publishingYearField.Text) && !int.TryParse(publishingYearField.Text, out publishingYear))
            {
                Errors.Add("publishingYear", Resources.Literature.BookPublishingYearIsIncorrect);
            }
            else if (!string.IsNullOrEmpty(publishingYearField.Text) && int.TryParse(publishingYearField.Text, out publishingYear) && (publishingYear < 1900 || publishingYear > 2099))
            {
                Errors.Add("publishingYear", Resources.Literature.BookPublishingYearIsIncorrect);
            }

            int pageCount;
            if (!string.IsNullOrEmpty(pageCountField.Text) && !int.TryParse(pageCountField.Text, out pageCount))
            {
                Errors.Add("pageCount", Resources.Literature.BookPagesCountIsIncorrect);
            }

            if (string.IsNullOrEmpty(additionalInfoField.Text) && (!additionalInfoField.Text.StartsWith("http://") && !additionalInfoField.Text.StartsWith("https://")) && (additionalInfoField.Text == "http://" || additionalInfoField.Text == "https://"))
            {
                Errors.Add("additionalInfo", Resources.Literature.BookInfoUrlIsIncorrect);
            }

            if ((additionalInfoField.Text == "http://") || (additionalInfoField.Text == "https://"))
            {
                Errors.Add("additionalInfo", Resources.Literature.BookInfoUrlIsIncorrect);
            }
            
            //TODO: Validate ISBN10 and ISBN13
            //protected TextBox ISBN10Field; - validate number if exists?
            //protected TextBox ISBN13Field; - validate number if exists?

            return (Errors.Count == 0);
        }

        /// <summary>
        /// Assign user premissions when editing literature
        /// </summary>
        private void AddApproverRoleToUser()
        {
            var userId = SPContext.Current.Web.CurrentUser.LoginName;
            var siteId = SPContext.Current.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var pubsite = new SPSite(siteId))
                using (var pubweb = pubsite.OpenWeb("/oppimine/raamatud/"))
                {
                    pubweb.AllowUnsafeUpdates = true;
                    var pubList = pubweb.Lists["Lehed"];

                    var cuser = pubweb.SiteUsers[userId];
                    
                    var assq = from a in pubList.RoleAssignments.Cast<SPRoleAssignment>()
                               from r in a.RoleDefinitionBindings.Cast<SPRoleDefinition>()
                               where a.Member.Name == cuser.LoginName &&
                                     r.Name == "Kinnitamine"
                               select a;

                    if (assq.Count() == 0)
                    {
                        Logger.LogInfo("SaveButtonClick(): assq is 0", GetType().ToString());
                        var ass2 = new SPRoleAssignment(cuser);
                        var rb2 = pubweb.RoleDefinitions["Kinnitamine"];
                        Logger.LogInfo("SaveButtonClick(): pubList.RoleAssignments = " + pubList.RoleAssignments.Count, GetType().ToString());
                        ass2.RoleDefinitionBindings.Add(rb2);
                        pubList.RoleAssignments.Add(ass2);
                        pubList.Update();
                    }
                    pubweb.AllowUnsafeUpdates = false;
                }
            });
        }

        /// <summary>
        /// Delete assigned preissions
        /// </summary>
        private void RemoveApproverRoleFromUser()
        {
            Logger.LogInfo("Vähendan kasutaja õiguseid", GetType().ToString());
            var userId2 = SPContext.Current.Web.CurrentUser.LoginName;
            var siteId = SPContext.Current.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var pubsite = new SPSite(siteId))
                using (var pubweb = pubsite.OpenWeb("/oppimine/raamatud/"))
                {
                    pubweb.AllowUnsafeUpdates = true;
                    var pubList = pubweb.Lists["Lehed"];

                    var cuser = pubweb.SiteUsers[userId2];

                    //var ass = pubList.RoleAssignments.GetAssignmentByPrincipal(cuser);
                    pubList.RoleAssignments.Remove(cuser);
                    pubList.Update();
                    pubweb.AllowUnsafeUpdates = false;
                }
            });
        }

        /// <summary>
        /// Bind field values, when item is set
        /// </summary>
        private void BindItem()
        {
            if (Item == null)
                return;

            if (!SPContext.Current.Web.CurrentUser.IsSiteAdmin && !IsAuthor)
            {
                Logger.LogInfo("Kasutaja ei ole administraator, suuname ümber", "BookEditPage_BindItem");
                Response.Redirect("/oppimine/raamatud", false);
                return;
            }

            titleLabel.Text = Item.Title;
            nameField.Text = Item.Title;
            descriptionField.Value = Item.Summary;
            authorsField.Text = Item.BookAuthors;
            publishingYearField.Text = Item.PublishingYear;
            pageCountField.Text = Item.PageCount;
            ISBN10Field.Text = Item.Isbn10;
            ISBN13Field.Text = Item.Isbn13;
            additionalInfoField.Text = Item.AdditionalInfoURL;
            if (!string.IsNullOrEmpty(Item.LiteratureImageUrl))
            {
                bookPreviewImage.Src = Item.LiteratureImageUrl;
                previewImage.Visible = true;
                bookPreviewImage.Visible = true;
            } 
        }

        /// <summary>
        /// Clearing default styles
        /// </summary>
        private void ClearStyles()
        {
            nameField.Attributes.Add("class", "info-row");
            //descriptionField.Attributes.Add("class", "info-row");
            authorsField.Attributes.Add("class", "info-row");
            publishingYearField.Attributes.Add("class", "info-row");
            pageCountField.Attributes.Add("class", "info-row");
            ISBN10Field.Attributes.Add("class", "info-row");
            ISBN13Field.Attributes.Add("class", "info-row");
            additionalInfoField.Attributes.Add("class", "info-row");
        }

        #endregion
    }
}
